package org.eclipse.snippets.code;

import java.util.LinkedList;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ExtendedModifyEvent;
import org.eclipse.swt.custom.ExtendedModifyListener;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;

public class Ch5Undoable extends Composite{

	 private static final int MAX_STACK_SIZE = 25;

	  private List undoStack;

	  private List redoStack;

	  private StyledText styledText;

	  public Ch5Undoable(Composite parent) {
	    super(parent, SWT.NONE);
	    undoStack = new LinkedList();
	    redoStack = new LinkedList();
	    buildControls();
	  }

	  private void buildControls() {
	    this.setLayout(new FillLayout());
	    styledText = new StyledText(this, SWT.MULTI | SWT.V_SCROLL);

	    styledText.addExtendedModifyListener(new ExtendedModifyListener() {
	      public void modifyText(ExtendedModifyEvent event) {
	        String currText = styledText.getText();
	        String newText = currText.substring(event.start, event.start
	            + event.length);
	        if (newText != null && newText.length() > 0) {
	          if (undoStack.size() == MAX_STACK_SIZE) {
	            undoStack.remove(undoStack.size() - 1);
	          }
	          undoStack.add(0, newText);
	        }
	      }
	    });

	    styledText.addKeyListener(new KeyAdapter() {
	      public void keyPressed(KeyEvent e) {
	        switch (e.keyCode) {
	        case SWT.F1:
	          undo();
	          break;
	        case SWT.F2:
	          redo();
	          break;
	        default:
	        //ignore everything else
	        }
	      }
	    });
	  }

	  private void undo() {
	    if (undoStack.size() > 0) {
	      String lastEdit = (String) undoStack.remove(0);
	      int editLength = lastEdit.length();
	      String currText = styledText.getText();
	      int startReplaceIndex = currText.length() - editLength;
	      styledText.replaceTextRange(startReplaceIndex, editLength, "");
	      redoStack.add(0, lastEdit);
	    }
	  }

	  private void redo() {
	    if (redoStack.size() > 0) {
	      String text = (String) redoStack.remove(0);
	      moveCursorToEnd();
	      styledText.append(text);
	      moveCursorToEnd();
	    }
	  }

	  private void moveCursorToEnd() {
	    styledText.setCaretOffset(styledText.getText().length());
	  }
}
